/*
  Copyright (c) 2010 Les Newell. All rights reserved

  This program is free software: you can redistribute it and/or modify
  it under the terms of the GNU General Public License as published by
  the Free Software Foundation, either version 3 of the License, or
  (at your option) any later version.

  This program is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  GNU General Public License for more details.

  You should have received a copy of the GNU General Public License
  along with this program. If not, see <http://www.gnu.org/licenses/>.
*/



#define UBLB(a,b)  ( ( (a) << 8) | (b) )
#define UBLB19(a,b) ( ( (a) << 16 ) | (b) )

class SPIComms
{
public:
    SPIComms()
    {
        pinMode(SPIDATAOUT, OUTPUT);
        pinMode(SPIDATAIN, INPUT);
        pinMode(SPICLOCK,OUTPUT);
        pinMode(SPISLAVESELECT,OUTPUT);
        digitalWrite(SPISLAVESELECT,HIGH); //Make sure we don't enter SPI slave mode
        SPCR = B01010011; //MPIE=0, SPE=1 (on), DORD=0 (MSB first), MSTR=1 (master), CPOL=0 (clock idle when low), CPHA=0 (samples MOSI on rising edge), SPR1=0 & SPR0=0 (500kHz)
    }

    char Transfer(char data)
    {
        int timeout=0;
        SPDR = data;            // Start the transmission
        while (!(SPSR & (1<<SPIF)))     // Wait for the end of the transmission
        {
            timeout++;
            if (timeout > 1000)
            {
                Errorln("SPI timeout");
                return(0);
            }
        };
        return SPDR;            // return the received byte
    }

    char Read(byte register_name)
    {
        char in_byte;
        register_name <<= 2;
        register_name &= B11111100; //Read command

        digitalWrite(SCPSELECT,LOW); //Select SPI Device
        Transfer(register_name); //Write byte to device
        in_byte = Transfer(0x00); //Send nothing, but we should get back the register value
        digitalWrite(SCPSELECT,HIGH);
        return(in_byte);
    }


    unsigned int Read16(char register_name)
    {
        byte in_byte1;
        byte in_byte2;
        unsigned int in_word;

        register_name <<= 2;
        register_name &= B11111100; //Read command

        digitalWrite(SCPSELECT,LOW); //Select SPI Device
        Transfer(register_name); //Write byte to device
        in_byte1 = Transfer(0x00);
        in_byte2 = Transfer(0x00);
        digitalWrite(SCPSELECT,HIGH);
        in_word = UBLB(in_byte1,in_byte2);
        return(in_word);
    }

    void Write(char register_name, char register_value)
    {
        register_name <<= 2;
        register_name |= B00000010; //Write command

        digitalWrite(SCPSELECT,LOW); //Select SPI device
        Transfer(register_name); //Send register location
        Transfer(register_value); //Send value to record into register
        digitalWrite(SCPSELECT,HIGH);
    }
};

SPIComms SPI;

